package com.example.zce.back.common.shiro;

import com.alibaba.fastjson.JSON;
import com.example.zce.back.common.constant.REDIS_KEY_CONSTANT;
import com.example.zce.back.common.constant.SESSION_CONSTANT;
import com.example.zce.back.common.redis.RedisService;
import com.example.zce.library.data.sys.constant.BackMenuEnum;
import com.example.zce.library.data.sys.constant.BackRoleEnum;
import com.example.zce.library.data.sys.constant.BackUserEnum;
import com.example.zce.library.data.sys.dao.BackRoleMenuMapper;
import com.example.zce.library.data.sys.dao.BackUserMapper;
import com.example.zce.library.data.sys.entity.BackMenu;
import com.example.zce.library.data.sys.entity.BackRole;
import com.example.zce.library.data.sys.entity.BackRoleMenu;
import com.example.zce.library.data.sys.entity.BackUser;
import com.example.zce.library.data.sys.model.BackMenuModel;
import com.example.zce.library.data.sys.model.BackUserModel;
import com.example.zce.library.data.sys.service.BackMenuService;
import com.example.zce.library.data.sys.service.BackRoleService;
import com.example.zce.library.data.sys.service.BackUserService;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 描述：shiro自定义ShiroRealm
 *
 * @author zengyz
 * @date 2018/7/27 13:29
 */
public class ShiroRealm extends AuthorizingRealm {

    private Logger log = LoggerFactory.getLogger(ShiroRealm.class);

    @Autowired
    private BackUserService backUserService;

    @Autowired
    private BackRoleService backRoleService;

    @Autowired
    private BackMenuService backMenuService;

    @Autowired
    private BackRoleMenuMapper backRoleMenuMapper;

    @Autowired
    private RedisService redisService;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        /**
         *   当没有使用缓存的时候，不断刷新页面的话，这个代码会不断执行，
         *   当其实没有必要每次都重新设置权限信息，所以我们需要放到缓存中进行管理；
         *   当放到缓存中时，这样的话，doGetAuthorizationInfo就只会执行一次了，
         *   缓存过期之后会再次执行。
         */

        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        BackUser backUser = (BackUser) principals.getPrimaryPrincipal();
        log.info("{}:权限控制开始", backUser.getAccount());
        //添加角色和权限
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        BackRole backRole = backRoleService.findById(backUser.getRoleId());
        simpleAuthorizationInfo.addRole(backRole.getCode());

        log.info("{}:权限控制开始｛角色：{}｝", backUser.getAccount(), backRole.getName());
        if (backRole.getState()==BackRoleEnum.STATE_NO.getIntegerValue()){
            log.info("{}:权限控制开始｛角色：{}｝,该角色被禁用", backUser.getAccount(), backRole.getName());
        }else{
            if (backRole.getCode().equals(BackRoleEnum.ADMIN_ROLE.getStringValue())){//admin用户配置不配置都有全部权限
                List<BackMenuModel> backMenuTree=new ArrayList<>();
                String backMenuStr = (String)redisService.get(REDIS_KEY_CONSTANT.MENU_TREE);
                if (StringUtils.isNotEmpty(backMenuStr)){
                    backMenuTree= JSON.parseArray(backMenuStr,BackMenuModel.class);
                }else{
                    backMenuTree = backMenuService.getBackMenuTree();
                }
                for (BackMenuModel backMenuModel:backMenuTree) {
                    simpleAuthorizationInfo.addStringPermission(backMenuModel.getCode());
                    for (BackMenuModel backPageModel:backMenuModel.getBackMenuModelList()) {
                        simpleAuthorizationInfo.addStringPermission(backPageModel.getCode());
                    }
                }
            }else{
                Map params=new HashMap();
                params.put("roleId",backRole.getId());
                List<BackRoleMenu> backRoleMenus = backRoleMenuMapper.selectListByParams(params);
                for (BackRoleMenu brm:backRoleMenus) {
                    BackMenu backMenu = backMenuService.findById(brm.getMenuId());
                    if (backMenu.getState()==BackMenuEnum.STATE_NO.getIntegerValue()){
                        log.info("{}:权限控制开始｛角色：{},权限：{}｝,该权限被禁用", backUser.getAccount(), backRole.getName(), backMenu.getName());
                    }else{
                        simpleAuthorizationInfo.addStringPermission(backMenu.getCode());
                        log.info("{}:权限控制开始｛角色：{},权限：{}｝", backUser.getAccount(), backRole.getName(), backMenu.getName());
                    }
                }
            }
        }
        log.info("{}:权限控制结束", backUser.getAccount());
        return simpleAuthorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        String account = String.valueOf(authenticationToken.getPrincipal());
        BackUser backUser = backUserService.findByLogin(account);
        if (null == backUser) {
            throw new UnknownAccountException();
        } else if (backUser.getState() == BackUserEnum.STATE_NO.getIntegerValue()) {
            throw new DisabledAccountException();
        } else {
            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(backUser, backUser.getPassword(), getName());
            Subject subject = SecurityUtils.getSubject();
            BackRole backRole = backRoleService.findById(backUser.getRoleId());
            BackUserModel init = BackUserModel.init(backUser, backRole);
            subject.getSession().setAttribute(SESSION_CONSTANT.SESSION_LOGIN_BACK_USER, init);
            return simpleAuthenticationInfo;
        }
    }
}
